package middleware

import (
	"context"
	"errors"
	"fmt"
	"gdmin/model"
	"gdmin/servlet"
	utils2 "gdmin/utils"
	"net/http"
	"time"

	"github.com/cloudwego/hertz/pkg/app"
	"github.com/cloudwego/hertz/pkg/common/hlog"
	"github.com/cloudwego/hertz/pkg/common/utils"
	"github.com/hertz-contrib/jwt"
)

var (
	JwtMiddleware *jwt.HertzJWTMiddleware
	IdentityKey   = "identity"
	UserIdKey     = "user_id"
)

func InitJwt() {
	var err error
	JwtMiddleware, err = jwt.New(&jwt.HertzJWTMiddleware{
		Realm:         "test zone",
		Key:           []byte("secret key"),
		Timeout:       5 * 24 * time.Hour,
		MaxRefresh:    7 * 24 * time.Hour,
		TokenLookup:   "header: Authorization, query: token, cookie: jwt",
		TokenHeadName: "Bearer",
		LoginResponse: func(ctx context.Context, c *app.RequestContext, code int, token string, expire time.Time) {
			h := utils.H{
				"token":  token,
				"expire": expire.Format(time.RFC3339),
			}

			servlet.OkWithData(c, &h)

			return
		},
		Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) {

			var req servlet.LoginReq

			if err := c.BindAndValidate(&req); err != nil {
				return nil, err
			}
			user, err := userService.Login(&req)
			if err != nil {
				return nil, err
			}
			if user.Id < 0 {
				return nil, errors.New("用户不存在")
			}

			return user, nil
		},
		IdentityKey: IdentityKey,
		IdentityHandler: func(ctx context.Context, c *app.RequestContext) interface{} {
			claims := jwt.ExtractClaims(ctx, c)
			user := model.User{
				LoginName: claims[IdentityKey].(string),
			}
			user.Id = int(claims[UserIdKey].(float64))
			utils2.SetThreadUserId(user.Id)

			return &user
		},
		PayloadFunc: func(data interface{}) jwt.MapClaims {
			if v, ok := data.(*model.User); ok {
				return jwt.MapClaims{
					IdentityKey: v.LoginName,
					UserIdKey:   v.Id,
				}
			}
			return jwt.MapClaims{}
		},
		HTTPStatusMessageFunc: func(e error, ctx context.Context, c *app.RequestContext) string {
			hlog.CtxErrorf(ctx, "jwt biz err = %+v", e.Error())
			return e.Error()
		},

		Unauthorized: func(ctx context.Context, c *app.RequestContext, code int, message string) {
			c.JSON(http.StatusOK, utils.H{
				"code":    code,
				"message": message,
			})
		},
		LogoutResponse: func(ctx context.Context, c *app.RequestContext, code int) {

			servlet.OkWithData(c, "退出成功")
			return

		},
	})
	if err != nil {
		panic(err)
	}
}

func Ping(ctx context.Context, c *app.RequestContext) {
	user, _ := c.Get(IdentityKey)
	hlog.Info("thread user id = ", utils2.GetThreadUserId())
	c.JSON(200, utils.H{
		"message": fmt.Sprintf("username:%v ,userId :%v", user.(*model.User).LoginName, user.(*model.User).Id),
	})
}
